package com.qd.hik.service;

import com.cdqidi.dto.CacheKey;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.RedisTemplateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qd.hik.base.HkBaseTokenDTO;
import com.qd.hik.dto.token.HkTokenResp;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 2.1 基础接口
 *
 * @author sjk
 * @create 2024-05-29 14:00
 * @since 1.0.0
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class HkTokenService {
    private final HkBaseTokenDTO hkBaseTokenDTO;
    private final ObjectMapper objectMapper;
    private final RedisTemplateUtil<HkTokenResp> redisTemplateUtil;
    private final Lock lock = new ReentrantLock();

    private static final String TOKEN_KEY = "hk_access_token";

    /**
     * 2.1.1  获取 access_token
     */
    private static final String TOKEN_URL = "/artemis/oauth/token";

    /**
     * 2.1.1  获取 access_token
     *
     * @return token超时时间
     */
    @SneakyThrows
    public HkTokenResp getToken() {
        Map<String, Object> params = new HashMap<>();
        params.put("client_id", hkBaseTokenDTO.getClientId());
        params.put("client_secret", hkBaseTokenDTO.getClientSecret());
        String post = cn.hutool.http.HttpUtil.post(hkBaseTokenDTO.getBaseUrl() + TOKEN_URL, params);
        HkTokenResp hkTokenResp = objectMapper.readValue(post, HkTokenResp.class);
        if (null == hkTokenResp.getExpiresIn()) {
            log.error("获取access_token失败，返回值：{}", post);
            throw new ApiException(hkTokenResp.getErrorDescription());
        }
        return hkTokenResp;
    }

    public HkTokenResp getTokenSync() {
        try {
            lock.lock();
            String key = RedisTemplateUtil.buildKey(TOKEN_KEY, true);
            HkTokenResp hkTokenResp = redisTemplateUtil.get(false, key, HkTokenResp.class);
            if (null == hkTokenResp) {
                hkTokenResp = getToken();
                redisTemplateUtil.set(new CacheKey().setKey(key).setTimeout((hkTokenResp.getExpiresIn() - 10) * 1000L), hkTokenResp);
            }
            return hkTokenResp;
        } finally {
            lock.unlock();
        }
    }
}